Introduction to Object-Oriented Programming (OOP) in Java
Course: Core Java Training
Topic: Introduction to Object-Oriented Programming (OOP)
Course Link: Core Java Training Course
Demo Link: Register for a Course Demo
Website: JustAcademy
1. Introduction to Object-Oriented Programming
Object-Oriented Programming (OOP) is a programming approach that organizes software around objects rather than relying entirely on separate functions and procedures. An object represents an entity that contains data and provides operations that work with that data.
Java is widely known as an object-oriented programming language because it supports classes, objects, encapsulation, inheritance, polymorphism, and abstraction. These concepts help developers create applications that are organized, reusable, maintainable, and easier to extend.
For example, a banking application may contain objects such as Customer, Account, Transaction, and Bank. Each object has its own data and operations that represent its responsibilities within the application.
Example of OOP in Everyday Life
Consider a car. A car has properties such as brand, color, speed, and fuel level. It also has behaviors such as starting, accelerating, braking, and stopping. In an OOP-based program, these properties can be represented by fields, while the behaviors can be represented by methods.
| Real-World Concept |
Java OOP Concept |
Example |
| Blueprint for cars |
Class |
Car |
| One particular car |
Object |
myCar |
| Car properties |
Fields |
color, speed |
| Car operations |
Methods |
start(), brake() |
| Protecting internal data |
Encapsulation |
Private fuelLevel field |
| Different car implementations |
Polymorphism |
Different start() implementations |
2. What Is Object-Oriented Programming?
OOP is a software development paradigm in which programs are designed using classes and objects. An object combines state and behavior, while a class defines the structure and behavior that its objects can share.
State: The data or current condition of an object, usually represented by fields.
Behavior: The actions an object can perform, usually represented by methods.
Identity: The distinct identity of an object, which allows it to be distinguished from other objects even when their data is identical.
Example
class Student {
String name;
int age;
void displayDetails() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
}
public class Main {
public static void main(String[] args) {
Student student = new Student();
student.name = "Aarav";
student.age = 20;
student.displayDetails();
}
}
Output:
Name: Aarav
Age: 20
In this example, Student is a class. The variable student refers to an object created from that class. The name and age fields represent the object's state, and displayDetails() represents its behavior.
3. Understanding Classes in Java
A class is a blueprint or template that defines the fields, methods, constructors, and other members that objects of that class can have. Declaring a class does not automatically create an instance of it.
Basic Class Syntax
class ClassName {
// Fields
// Constructors
// Methods
}
Example: Employee Class
class Employee {
int employeeId;
String employeeName;
double salary;
void displayEmployee() {
System.out.println("ID: " + employeeId);
System.out.println("Name: " + employeeName);
System.out.println("Salary: " + salary);
}
}
The Employee class defines three fields and one method. Objects created from this class can hold employee details and display them.
Important Characteristics of a Class
- A class defines the structure of its objects.
- It can contain fields, methods, constructors, nested types, and initialization blocks.
- Access modifiers control how its members can be accessed.
- A class can implement interfaces and, where permitted, extend another class.
- A class may define instance members and static members.
4. Understanding Objects in Java
An object is an instance of a class. It can hold its own instance-field values and provide access to the behavior defined by its class, subject to Java's access rules.
Objects are commonly created using the new keyword, which creates an instance and invokes a constructor. A reference variable can then refer to that object.
Creating an Object
Student student = new Student();
This statement declares a reference variable named student and assigns it a reference to a newly created Student object.
Creating Multiple Objects
class Student {
String name;
int age;
void display() {
System.out.println(name + " - " + age);
}
}
public class Main {
public static void main(String[] args) {
Student s1 = new Student();
s1.name = "Aarav";
s1.age = 20;
Student s2 = new Student();
s2.name = "Meera";
s2.age = 22;
s1.display();
s2.display();
}
}
Output:
Aarav - 20
Meera - 22
Both objects belong to the same class, but each has its own instance-field values. Updating s1.name does not automatically change s2.name.
5. The Four Main Pillars of OOP
The four commonly taught pillars of object-oriented programming are encapsulation, inheritance, polymorphism, and abstraction. Each addresses a different aspect of software design.
| Pillar |
Meaning |
Primary Benefit |
| Encapsulation |
Keeping data and related behavior together while controlling access to internal state |
Data protection and maintainability |
| Inheritance |
Creating a class that derives from another class |
Reuse and specialization |
| Polymorphism |
Allowing a common interface or superclass reference to represent different implementations |
Flexible and extensible code |
| Abstraction |
Exposing essential operations while hiding implementation details |
Reduced complexity |
6. Encapsulation
Encapsulation means grouping data and the methods that operate on it within a class while controlling how the internal state is accessed or changed. In Java, it is commonly implemented by declaring fields private and providing carefully designed public methods when access is needed.
Encapsulation helps a class enforce rules. For example, a bank account should not allow its balance to be set to an arbitrary negative value through unrestricted public field access.
Example of Encapsulation
class BankAccount {
private double balance;
public BankAccount(double initialBalance) {
if (initialBalance < 0) {
throw new IllegalArgumentException(
"Initial balance cannot be negative"
);
}
balance = initialBalance;
}
public double getBalance() {
return balance;
}
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
}
public class Main {
public static void main(String[] args) {
BankAccount account = new BankAccount(1000);
account.deposit(500);
System.out.println(account.getBalance());
}
}
Output:
1500.0
The balance field is private, so unrelated code cannot directly assign a value to it. The class provides controlled operations for accessing and updating the balance.
Benefits of Encapsulation
- Protects internal state from uncontrolled modification.
- Allows validation before accepting changes.
- Reduces dependencies on implementation details.
- Makes future changes easier because internal implementation can evolve behind a stable interface.
7. Inheritance
Inheritance allows a class to extend another class and acquire accessible members and behavior from it. The existing class is called the superclass or parent class, and the class that extends it is called the subclass or child class.
Java uses the extends keyword for class inheritance. A subclass can add new behavior or override eligible inherited methods to provide a specialized implementation.
Example of Inheritance
class Animal {
void eat() {
System.out.println("Animal is eating");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Dog is barking");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
dog.bark();
}
}
Output:
Animal is eating
Dog is barking
Dog inherits the accessible eat() method from Animal and defines its own bark() method.
Common Inheritance Forms in Java
| Form |
Description |
Java Support |
| Single |
One subclass extends one superclass |
Supported |
| Multilevel |
A class extends a subclass in a chain |
Supported |
| Hierarchical |
Multiple subclasses extend the same superclass |
Supported |
| Multiple inheritance of classes |
A class directly extends multiple classes |
Not supported |
| Multiple inheritance through interfaces |
A class implements multiple interfaces |
Supported |
Inheritance should represent a genuine “is-a” relationship. For example, Dog is an Animal. If two classes merely need to use the same service, composition may be a better choice than inheritance.
8. Polymorphism
Polymorphism means “many forms.” In Java, it allows a common method name, superclass reference, or interface to work with different implementations.
Two important forms of polymorphism commonly taught in Java are compile-time polymorphism through method overloading and runtime polymorphism through method overriding.
8.1 Compile-Time Polymorphism: Method Overloading
Method overloading occurs when a class defines multiple methods with the same name but different parameter lists. The compiler selects the appropriate overload based on the arguments and the applicable method-resolution rules.
class Calculator {
int add(int a, int b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
double add(double a, double b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(10, 20));
System.out.println(calc.add(10, 20, 30));
System.out.println(calc.add(2.5, 3.5));
}
}
Output:
30
60
6.0
These methods share the name add but accept different parameter lists. Changing only a method's return type is not sufficient to overload it.
8.2 Runtime Polymorphism: Method Overriding
Method overriding occurs when a subclass provides an implementation of an eligible inherited instance method with a compatible signature. When the method is called through a superclass reference, Java selects the implementation based on the actual object's runtime class.
class Animal {
void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Cat meows");
}
}
public class Main {
public static void main(String[] args) {
Animal first = new Dog();
Animal second = new Cat();
first.makeSound();
second.makeSound();
}
}
Output:
Dog barks
Cat meows
Although both variables have the declared type Animal, the objects are Dog and Cat. The overridden implementation is selected according to each object's runtime class.
Benefits of Polymorphism
- Allows different implementations to be used through a common type.
- Reduces the need for repetitive conditional logic.
- Makes programs easier to extend with new classes.
- Supports flexible designs that depend on interfaces or abstract classes.
9. Abstraction
Abstraction focuses on what an object can do rather than exposing every detail of how it performs an operation. It reduces complexity by presenting a clear interface to the rest of the program.
Java supports abstraction through abstract classes and interfaces. Abstract classes can contain abstract methods as well as implemented methods and instance state. Interfaces define contracts that implementing classes agree to fulfill, and they can also contain default, static, and private methods where permitted by Java's rules.
Example Using an Abstract Class
abstract class Shape {
abstract double calculateArea();
void describe() {
System.out.println("This is a shape");
}
}
class Circle extends Shape {
private final double radius;
Circle(double radius) {
this.radius = radius;
}
@Override
double calculateArea() {
return Math.PI * radius * radius;
}
}
public class Main {
public static void main(String[] args) {
Shape shape = new Circle(5);
shape.describe();
System.out.printf("Area: %.2f%n", shape.calculateArea());
}
}
Output:
This is a shape
Area: 78.54
Shape declares the operation calculateArea() without specifying the exact formula. Circle supplies the implementation for its own shape.
Abstract Class vs Interface
| Feature |
Abstract Class |
Interface |
| Declaration |
Uses the abstract class declaration |
Uses the interface keyword |
| Inheritance or implementation |
A class extends one superclass |
A class can implement multiple interfaces |
| Instance fields |
Can contain instance fields |
Fields are implicitly public, static, and final |
| Constructors |
Can define constructors |
Cannot define constructors |
| Methods |
Can contain abstract and concrete instance methods |
Can declare abstract methods and permitted default, static, and private methods |
| Typical purpose |
Share common state and implementation |
Define a capability or contract |
10. How the Four Pillars Work Together
Consider an online payment application. It can use all four pillars to organize payment processing.
- Encapsulation: A payment class controls access to transaction details and validates permitted operations.
- Inheritance: Specialized payment classes may extend a common payment superclass when their relationship justifies inheritance.
- Polymorphism: A common Payment interface can be implemented by card, bank-transfer, and wallet payment classes.
- Abstraction: The checkout process calls a payment operation without needing to know every provider-specific implementation detail.
Example Using an Interface and Polymorphism
interface Payment {
void pay(double amount);
}
class CardPayment implements Payment {
@Override
public void pay(double amount) {
System.out.println("Paid " + amount + " using a card");
}
}
class WalletPayment implements Payment {
@Override
public void pay(double amount) {
System.out.println("Paid " + amount + " using a wallet");
}
}
public class Main {
public static void main(String[] args) {
Payment payment = new CardPayment();
payment.pay(1200);
payment = new WalletPayment();
payment.pay(500);
}
}
Output:
Paid 1200.0 using a card
Paid 500.0 using a wallet
The calling code uses the same Payment contract for different implementations. In a real payment system, authentication, transaction verification, error handling, and secure handling of payment data would also be essential.
11. Constructors and Object Initialization
A constructor is a special class member used to initialize a newly created object. Its name matches the class name, and it has no return type, not even void.
Java provides a default constructor automatically only when no constructor is declared in the class. If a programmer declares a constructor, the compiler does not automatically provide that no-argument default constructor.
Example of a Parameterized Constructor
class Book {
private String title;
private double price;
Book(String title, double price) {
this.title = title;
this.price = price;
}
void display() {
System.out.println("Title: " + title);
System.out.println("Price: " + price);
}
}
public class Main {
public static void main(String[] args) {
Book book = new Book("Java Basics", 450.0);
book.display();
}
}
Output:
Title: Java Basics
Price: 450.0
The constructor initializes the object's fields when the Book object is created. The keyword this refers to the current object, helping distinguish instance fields from parameters with the same names.
12. Instance Members and Static Members
Instance members belong to individual objects. Each object generally has its own instance-field values. Static members belong to the class itself and are shared at the class level rather than being separately associated with each instance.
class Employee {
private String name;
private static int employeeCount = 0;
Employee(String name) {
this.name = name;
employeeCount++;
}
void display() {
System.out.println("Employee: " + name);
}
static int getEmployeeCount() {
return employeeCount;
}
}
public class Main {
public static void main(String[] args) {
Employee e1 = new Employee("Aarav");
Employee e2 = new Employee("Meera");
e1.display();
e2.display();
System.out.println(Employee.getEmployeeCount());
}
}
Output:
Employee: Aarav
Employee: Meera
2
The name field belongs to each Employee object, while employeeCount is a static field shared by the class. Static methods cannot directly access instance members without an object reference.
13. Access Modifiers in Java OOP
Access modifiers control where classes and their members can be accessed. Choosing appropriate access levels supports encapsulation and helps define a clear public interface.
| Modifier |
Same Class |
Same Package |
Subclass in Another Package |
Unrelated Class in Another Package |
| private |
Yes |
No direct access |
No direct access |
No direct access |
| Default (package-private) |
Yes |
Yes |
No |
No |
| protected |
Yes |
Yes |
Yes, subject to subclass access rules |
No |
| public |
Yes |
Yes |
Yes, subject to other language and module rules |
Yes, subject to other language and module rules |
Top-level classes can normally be declared public or package-private. The private and protected modifiers are not permitted on ordinary top-level class declarations, though nested classes can use them.
14. Advantages of Object-Oriented Programming
- Modularity: Applications can be divided into classes with clear responsibilities.
- Reusability: Existing classes and interfaces can be reused in different parts of a project.
- Maintainability: Well-designed classes make changes easier to isolate.
- Extensibility: New implementations can often be introduced without rewriting all calling code.
- Data protection: Encapsulation limits uncontrolled access to internal state.
- Testability: Components with clear responsibilities and interfaces are often easier to test independently.
- Real-world modeling: Classes can represent concepts such as customers, orders, products, and accounts.
15. Limitations and Challenges of OOP
- Overusing classes can make a simple program unnecessarily complicated.
- Deep inheritance hierarchies can make behavior difficult to trace.
- Poorly designed objects can become tightly coupled and difficult to test.
- Creating and managing many objects may introduce memory and performance overhead in some applications.
- OOP does not automatically guarantee secure, efficient, or maintainable software; design quality remains important.
A practical approach is to use OOP where it clarifies the problem. Prefer small classes, clear interfaces, appropriate access control, and composition when those choices produce simpler designs.
16. OOP vs Procedural Programming
| Basis |
Object-Oriented Programming |
Procedural Programming |
| Main organization |
Classes and objects |
Procedures or functions |
| Data and behavior |
Often grouped in objects |
Often organized separately |
| Code reuse |
Can use composition, inheritance, interfaces, and delegation |
Can use reusable functions and modules |
| Data access |
Can use encapsulation and access modifiers |
Depends on the language and program design |
| Best suited for |
Many systems with collaborating entities and evolving behavior |
Many algorithmic, sequential, or function-oriented tasks |
Neither paradigm is universally better. The appropriate design depends on the problem, complexity, language features, and maintenance needs.
17. Common Mistakes When Learning OOP
| Mistake |
Why It Is a Problem |
Better Practice |
| Confusing a class with an object |
A blueprint is not the same as an instance created from it. |
Identify the class declaration and the object creation statement separately. |
| Making every field public |
Any accessible code may change state without validation. |
Use private fields and expose controlled operations when appropriate. |
| Using inheritance only to reuse code |
The relationship may not represent a true subtype. |
Consider composition and delegation. |
| Confusing overloading with overriding |
They follow different method-resolution rules. |
Overloading changes the parameter list; overriding specializes an inherited method. |
| Assuming an interface is an object |
An interface defines a type and contract, not a directly instantiable class. |
Create an instance of a concrete implementing class. |
| Ignoring constructors and initialization |
Objects may begin in an unintended state. |
Initialize required fields and validate input during construction. |
| Creating classes for every tiny operation |
Unnecessary abstractions increase complexity. |
Keep the design proportional to the problem. |
18. Step-by-Step Guide to Designing an OOP Program
- Understand the problem: Write down the requirements and expected behavior.
- Identify entities: Find important concepts such as Customer, Product, Order, or Payment.
- Define responsibilities: Decide what data and operations belong to each class.
- Choose relationships: Determine whether classes should use composition, inheritance, or interfaces.
- Protect internal state: Apply access modifiers and validation rules.
- Implement constructors and methods: Ensure objects begin in valid states and provide clear behavior.
- Test individual classes: Verify normal operations, boundary cases, and invalid inputs.
- Review the design: Remove duplicated logic and simplify unnecessary dependencies.
19. Mini Project: Student Management System
This beginner project demonstrates classes, objects, encapsulation, constructors, and methods in a small application.
Project Requirements
- Create a Student class with a name, roll number, and marks.
- Keep fields private to control direct access.
- Initialize the student using a constructor.
- Provide a method to display student information.
- Validate marks so they remain within the range 0 to 100.
Implementation
class Student {
private String name;
private int rollNumber;
private double marks;
Student(String name, int rollNumber, double marks) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException(
"Name cannot be empty"
);
}
if (rollNumber <= 0) {
throw new IllegalArgumentException(
"Roll number must be positive"
);
}
setMarks(marks);
this.name = name;
this.rollNumber = rollNumber;
}
public void setMarks(double marks) {
if (marks < 0 || marks > 100) {
throw new IllegalArgumentException(
"Marks must be between 0 and 100"
);
}
this.marks = marks;
}
public void displayDetails() {
System.out.println("Name: " + name);
System.out.println("Roll Number: " + rollNumber);
System.out.println("Marks: " + marks);
}
}
public class Main {
public static void main(String[] args) {
Student student = new Student("Meera", 101, 88.5);
student.displayDetails();
}
}
Output:
Name: Meera
Roll Number: 101
Marks: 88.5
Project Extension Ideas
- Add a method to calculate a grade based on marks.
- Create multiple Student objects and display each student's information.
- Store students in an ArrayList.
- Introduce a Course class and associate students with courses.
- Add search functionality using roll number.
- Write unit tests for valid and invalid student data.
20. Practice Exercises
- Create a Car class with brand, model, and speed fields, plus accelerate() and brake() methods.
- Create a Book class with a parameterized constructor and a method that displays book details.
- Implement encapsulation in a BankAccount class with deposit() and withdraw() methods.
- Create an Animal superclass and Dog and Cat subclasses that override makeSound().
- Define a Shape interface with a calculateArea() method and implement it in Circle and Rectangle classes.
- Create a Calculator class that overloads the add() method for different parameter lists.
- Build a small employee management program using multiple Employee objects.
- Explain whether composition or inheritance is more suitable for a Car that uses an Engine object.
21. Interview Questions and Answers
Q1. What is OOP?
Answer: Object-Oriented Programming is a programming paradigm that organizes code around objects containing state and behavior. It supports concepts such as encapsulation, inheritance, polymorphism, and abstraction.
Q2. What is a class in Java?
Answer: A class is a blueprint that defines the fields, methods, constructors, and other members available to its objects.
Q3. What is an object?
Answer: An object is an instance of a class. It has identity and can maintain state through its instance fields while providing behavior through methods.
Q4. What are the four pillars of OOP?
Answer: Encapsulation, inheritance, polymorphism, and abstraction.
Q5. What is encapsulation?
Answer: Encapsulation combines data and related behavior within a class and controls access to internal state. Private fields and public methods are a common implementation pattern.
Q6. What is inheritance?
Answer: Inheritance allows a subclass to extend a superclass, reuse accessible behavior, and specialize inherited methods.
Q7. Does Java support multiple inheritance?
Answer: Java does not support a class extending multiple classes. A class can implement multiple interfaces, which provide a way to combine multiple type contracts.
Q8. What is polymorphism?
Answer: Polymorphism allows common types or method names to work with different implementations. Method overloading is resolved at compile time, while overridden instance methods use runtime dispatch.
Q9. What is abstraction?
Answer: Abstraction exposes essential operations while hiding implementation details. Java provides abstract classes and interfaces to support abstraction.
Q10. What is the difference between overloading and overriding?
Answer: Overloading defines methods with the same name but different parameter lists. Overriding provides a compatible implementation of an inherited instance method in a subclass.
Q11. What is the difference between an abstract class and an interface?
Answer: An abstract class can contain instance state, constructors, and implemented methods. An interface defines a contract that classes can implement, and a class can implement multiple interfaces.
Q12. What is a constructor?
Answer: A constructor initializes a newly created object. It has the same name as the class and no return type.
Q13. What does the this keyword mean?
Answer: The this keyword refers to the current object in an instance context. It is often used to distinguish instance fields from parameters with identical names.
Q14. What is the difference between static and instance members?
Answer: Instance members are associated with individual objects, whereas static members belong to the class and are shared at the class level.
Q15. What is composition?
Answer: Composition is a design technique in which one object contains or collaborates with another object to provide functionality. It often offers more flexibility than inheritance when modeling a “has-a” relationship.
22. Quick Revision Notes
- OOP organizes software around classes and objects.
- A class defines structure and behavior; an object is an instance of a class.
- Fields generally represent state, while methods represent behavior.
- Encapsulation controls access to internal state.
- Inheritance supports specialization through superclass and subclass relationships.
- Polymorphism lets common types work with different implementations.
- Overloading uses different parameter lists; overriding specializes inherited behavior.
- Abstraction exposes essential operations and hides implementation details.
- Constructors initialize newly created objects.
- Static members belong to the class; instance members belong to objects.
- Access modifiers help establish clear boundaries around class members.
- Use composition when a “has-a” relationship is more appropriate than an “is-a” relationship.
23. OOP Best Practices
- Give every class a clear and focused responsibility.
- Keep fields private when direct access is not part of the intended design.
- Validate constructor inputs and state-changing operations.
- Prefer meaningful class, method, and variable names.
- Use interfaces to define contracts between components where useful.
- Apply inheritance only when the subtype relationship is appropriate.
- Prefer composition when it leads to simpler and more flexible designs.
- Avoid unnecessary abstraction and overly deep inheritance hierarchies.
- Write tests for expected behavior, edge cases, and invalid input.
- Follow Java naming conventions: class names use UpperCamelCase, and method and variable names use lowerCamelCase.
24. Conclusion
Object-Oriented Programming is a fundamental part of Core Java. Understanding classes, objects, encapsulation, inheritance, polymorphism, and abstraction provides a foundation for building structured Java applications. Constructors, access modifiers, interfaces, and composition further help developers create reliable and maintainable software.
The best way to learn OOP is to write small programs, create multiple objects, experiment with method overriding and interfaces, and gradually build projects that model real-world requirements.
Explore Core Java Training: View the Core Java Training Course
Register for a Demo: Register for a Course Demo
Visit JustAcademy: https://www.justacademy.co/